package com.example.composemodifiterdemo

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.FractionalThreshold
import androidx.compose.material.rememberSwipeableState
import androidx.compose.material.swipeable
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.consumeAllChanges
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlin.math.roundToInt

/**
 * @auth: njb
 * @date: 2023/1/1 23:29
 * @desc: 手势
 */
class GesturesActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // ClickableSample()
            //ScrollBoxes()
            //ScrollBoxesSmooth()
            //ScrollableSample()
            //singleDraggableSample()
            //DraggableSample()
            //SwipeAbleSample()
            //TransformableSample()
            AllGestures()
        }
    }


    @Composable
    fun ClickableSample() {
        val count = remember { mutableStateOf(0) }
        Box(
            modifier = Modifier
                .size(200.dp)
                .background(Color.DarkGray)
                .clickable { count.value += 1 },
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "点击改变" + count.value.toString(),
                style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
            )
        }
    }

    @Composable
    fun ScrollBoxes() {
        val state = rememberScrollState()
        LaunchedEffect(Unit) { state.animateScrollTo(200) }
        Column(
            modifier = Modifier
                .background(Color.LightGray)
                .size(200.dp)
                .padding(horizontal = 8.dp)
                .verticalScroll(state)
        ) {
            repeat(20) {
                Text("滚动的Item $it", modifier = Modifier.padding(2.dp))
            }
        }
    }

    @Composable
    private fun ScrollBoxesSmooth() {
        var offsets: Float by remember { mutableStateOf(0f) }
        Box(
            Modifier
                .size(200.dp)
                .scrollable(
                    orientation = Orientation.Vertical,
                    // Scrollable state: describes how to consume
                    // scrolling delta and update offset
                    state = rememberScrollableState { delta ->
                        offsets += delta
                        delta
                    }
                )
                .background(Color.LightGray),
            contentAlignment = Alignment.Center
        ) {
            Text(offsets.toString())
        }
    }

    @Composable
    fun ScrollableSample() {
        // actual composable state
        var offset by remember { mutableStateOf(0f) }
        Box(
            Modifier
                .size(200.dp)
                .scrollable(
                    orientation = Orientation.Vertical,
                    // Scrollable state: describes how to consume
                    // scrolling delta and update offset
                    state = rememberScrollableState { delta ->
                        offset += delta
                        delta
                    }
                )
                .background(Color.LightGray),
            contentAlignment = Alignment.Center
        ) {
            Text(offset.toString())
        }

        val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White)
        Box(
            modifier = Modifier
                .background(Color.LightGray)
                .verticalScroll(rememberScrollState())
                .padding(32.dp)
        ) {
            Column {
                repeat(6) {
                    Box(
                        modifier = Modifier
                            .height(128.dp)
                            .verticalScroll(rememberScrollState())
                    ) {
                        Text(
                            "Scroll here",
                            modifier = Modifier
                                .border(12.dp, Color.DarkGray)
                                .background(brush = gradient)
                                .padding(24.dp)
                                .height(200.dp)
                        )
                    }
                }
            }
        }
    }

    @Composable
    fun singleDraggableSample() {
        var offsetX by remember { mutableStateOf(0f) }
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(200.dp)
                .offset { IntOffset(offsetX.roundToInt(), 0) }
                .draggable(
                    state = rememberDraggableState {
                        offsetX += it
                    },
                    orientation = Orientation.Horizontal
                )
                .background(Color.Red),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "单一拖动",
                style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
            )
        }
    }

    @Composable
    fun DraggableSample() {
        Box(modifier = Modifier.fillMaxSize()) {
            var offsetX by remember { mutableStateOf(0f) }
            var offsetY by remember { mutableStateOf(0f) }
            Box(
                Modifier
                    .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                    .background(Color.Blue)
                    .size(200.dp)
                    .pointerInput(Unit) {
                        detectDragGestures { change, dragAmount ->
                            change.consumeAllChanges()
                            offsetX += dragAmount.x
                            offsetY += dragAmount.y
                        }
                    }
            ) {
                Text(
                    text = "任意位置拖动",
                    style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                )
            }
        }
    }

    @OptIn(ExperimentalMaterialApi::class)
    @Composable
    fun SwipeAbleSample() {
        val width = 200.dp
        val squareSize = 100.dp

        val swipeAbleState = rememberSwipeableState(0)
        val sizePx = with(LocalDensity.current) { squareSize.toPx() }
        val anchors = mapOf(0f to 0, sizePx to 1) // Maps anchor points (in px) to states

        Box(
            modifier = Modifier
                .width(width)
                .swipeable(
                    state = swipeAbleState,
                    anchors = anchors,
                    thresholds = { _, _ -> FractionalThreshold(0.3f) },
                    orientation = Orientation.Horizontal
                )
                .background(Color.LightGray),
            contentAlignment = Alignment.CenterStart
        ) {
            Box(
                Modifier
                    .offset { IntOffset(swipeAbleState.offset.value.roundToInt(), 0) }
                    .size(squareSize)
                    .background(Color.DarkGray)
            )
            Text(
                text = "左右滑动",
                textAlign = TextAlign.Center,
                style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
            )
        }
    }

    @Composable
    fun TransformableSample() {
        // set up all transformation states
        var scale by remember { mutableStateOf(1f) }
        var rotation by remember { mutableStateOf(0f) }
        var offset by remember { mutableStateOf(Offset.Zero) }
        val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
            scale *= zoomChange
            rotation += rotationChange
            offset += offsetChange
        }
        Box(
            Modifier
                // apply other transformations like rotation and zoom
                // on the pizza slice emoji
                .graphicsLayer(
                    scaleX = scale,
                    scaleY = scale,
                    rotationZ = rotation,
                    translationX = offset.x,
                    translationY = offset.y
                )
                // add transformable to listen to multitouch transformation events
                // after offset
                .transformable(state = state)
                .background(Color.Blue)
                .size(200.dp)
        )
    }

    @OptIn(ExperimentalMaterialApi::class)
    @Composable
    private fun AllGestures() {
        Column(modifier = Modifier.fillMaxSize()) {
            // content that you want to make clickable
            Row {
                val count = remember { mutableStateOf(0) }
                Box(
                    modifier = Modifier
                        .size(200.dp)
                        .background(Color.DarkGray)
                        .clickable { count.value += 1 },
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = "点击改变" + count.value.toString(),
                        style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                    )
                }
                Spacer(modifier = Modifier.width(30.dp))
                // Smoothly scroll 100px on first composition
                val states = rememberScrollState()
                LaunchedEffect(Unit) { states.animateScrollTo(200) }
                Column(
                    modifier = Modifier
                        .background(Color.Magenta)
                        .size(200.dp)
                        .padding(horizontal = 8.dp)
                        .verticalScroll(states)
                ) {
                    repeat(20) {
                        Text(
                            "滚动的Item $it",
                            modifier = Modifier.padding(2.dp),
                            style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                        )
                    }
                }
                Spacer(modifier = Modifier.width(20.dp))
                // actual composable state
                var offsets: Float by remember { mutableStateOf(0f) }
                Box(
                    Modifier
                        .size(200.dp)
                        .scrollable(
                            orientation = Orientation.Vertical,
                            // Scrollable state: describes how to consume
                            // scrolling delta and update offset
                            state = rememberScrollableState { delta ->
                                offsets += delta
                                delta
                            }
                        )
                        .background(Color.LightGray),
                    contentAlignment = Alignment.Center
                ) {
                    Text(offsets.toString())
                }
            }
            //嵌套滚动
            Row() {
                Spacer(Modifier.width(20.dp))
                val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White)
                Box(
                    modifier = Modifier
                        .background(Color.LightGray)
                        .verticalScroll(rememberScrollState())
                        .padding(32.dp)
                ) {
                    Column {
                        repeat(6) {
                            Box(
                                modifier = Modifier
                                    .height(128.dp)
                                    .verticalScroll(rememberScrollState())
                            ) {
                                Text(
                                    "Scroll here",
                                    modifier = Modifier
                                        .border(12.dp, Color.DarkGray)
                                        .background(brush = gradient)
                                        .padding(24.dp)
                                        .height(200.dp)
                                )
                            }
                        }
                    }
                }
                Spacer(modifier = Modifier.width(20.dp))
                //左右滑动
                val width = 200.dp
                val squareSize = 100.dp
                val swipeAbleState = rememberSwipeableState(0)
                val sizePx = with(LocalDensity.current) { squareSize.toPx() }
                val anchors = mapOf(0f to 0, sizePx to 1) // Maps anchor points (in px) to states
                Box(
                    modifier = Modifier
                        .width(width)
                        .swipeable(
                            state = swipeAbleState,
                            anchors = anchors,
                            thresholds = { _, _ -> FractionalThreshold(0.3f) },
                            orientation = Orientation.Horizontal
                        )
                        .background(Color.LightGray),
                    contentAlignment = Alignment.CenterStart
                ) {
                    Box(
                        Modifier
                            .offset { IntOffset(swipeAbleState.offset.value.roundToInt(), 0) }
                            .size(squareSize)
                            .background(Color.Cyan)
                    )
                    Text(
                        text = "左右滑动",
                        textAlign = TextAlign.Center,
                        style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                    )
                }
                Spacer(modifier = Modifier.width(20.dp))
                var offsetX by remember { mutableStateOf(0f) }
                var offsetY by remember { mutableStateOf(0f) }
                Box(
                    modifier = Modifier
                        .size(100.dp)
                        .offset { IntOffset(offsetX.roundToInt(), 0) }
                        .draggable(
                            state = rememberDraggableState {
                                offsetX += it
                            },
                            orientation = Orientation.Horizontal
                        )
                        .background(Color.Red),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = "单一拖动",
                        style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                    )
                }
                Spacer(modifier = Modifier.width(20.dp))
                //拖动任意位置
                var offX by remember { mutableStateOf(0f) }
                var offY by remember { mutableStateOf(0f) }
                Box(
                    Modifier
                        .offset { IntOffset(offX.roundToInt(), offY.roundToInt()) }
                        .background(Color.Blue)
                        .size(200.dp)
                        .pointerInput(Unit) {
                            detectDragGestures { change, dragAmount ->
                                change.consumeAllChanges()
                                offX += dragAmount.x
                                offY += dragAmount.y
                            }
                        },
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = "任意位置拖动",
                        style = MaterialTheme.typography.bodySmall.copy(color = Color.White)
                    )
                }

                Spacer(modifier = Modifier.width(20.dp))
                // set up all transformation states
                var scale by remember { mutableStateOf(1f) }
                var rotation by remember { mutableStateOf(0f) }
                var offset by remember { mutableStateOf(Offset.Zero) }
                val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
                    scale *= zoomChange
                    rotation += rotationChange
                    offset += offsetChange
                }
                Box(
                    Modifier
                        // apply other transformations like rotation and zoom
                        // on the pizza slice emoji
                        .graphicsLayer(
                            scaleX = scale,
                            scaleY = scale,
                            rotationZ = rotation,
                            translationX = offset.x,
                            translationY = offset.y
                        )
                        // add transformable to listen to multitouch transformation events
                        // after offset
                        .transformable(state = state)
                        .background(Color.Blue)
                        .width(200.dp)
                )
            }
        }
    }
}